package com.sduept.nwld.dataserver.controller.equipment.assessment;

import com.alibaba.fastjson.JSONObject;
import com.sduept.bigdata.equipment.assessment.enums.ItemTypeEnum;
import com.sduept.bigdata.equipment.assessment.enums.SubStationTypeEnum;
import com.sduept.bigdata.equipment.assessment.exception.ParameterException;
import com.sduept.bigdata.equipment.assessment.model.inspection.InspectionExpert;
import com.sduept.bigdata.equipment.assessment.model.inspection.InspectionItem;
import com.sduept.bigdata.equipment.assessment.model.inspection.InspectionStation;
import com.sduept.bigdata.equipment.assessment.model.standardlib.StandardInspection;
import com.sduept.bigdata.equipment.assessment.service.InspectionExpertService;
import com.sduept.bigdata.equipment.assessment.service.InspectionItemService;
import com.sduept.bigdata.equipment.assessment.service.InspectionStationService;
import com.sduept.bigdata.equipment.assessment.service.StandardInspectService;
import com.sduept.cim.ledger.enums.ManagementUnitEnum;
import com.sduept.cim.ledger.excetpion.ManagementUnitException;
import com.sduept.cim.ledger.manager.SubstationLedgerManager;
import com.sduept.cim.ledger.model.ManagementUnitDict;
import com.sduept.cim.ledger.model.SubstationLedger;
import com.sduept.cim.ledger.services.ManagementUnitService;
import com.sduept.cim.model.core.Substation;
import com.sduept.core.dao.SuperDAO;
import com.sduept.bigdata.web.jsf.controller.AbstractController;
import com.sduept.bigdata.weather.map.MapDataCache;
import com.sduept.nwld.dataserver.manager.cim.CimManager;
import com.sduept.permission.entity.DepartmentEntityBean;
import com.sduept.permission.manager.DepartManager;
import org.apache.commons.lang3.StringUtils;
import org.primefaces.PrimeFaces;
import org.primefaces.event.FlowEvent;
import org.primefaces.event.NodeExpandEvent;
import org.primefaces.event.NodeSelectEvent;
import org.primefaces.event.NodeUnselectEvent;
import org.primefaces.model.DefaultTreeNode;
import org.primefaces.model.TreeNode;
import org.springframework.beans.factory.annotation.Autowired;

import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.view.ViewScoped;
import javax.inject.Named;
import java.util.*;
/**
 * 评价站选择器后台控制类
 * @author pengz
 *
 */
@Named
@ViewScoped
public class InspectionStationSelectorController extends AbstractController{

	private static final long serialVersionUID = 2381400096708969884L;
	
	@Autowired
	private DepartManager dm;
	@Autowired
	private InspectionExpertService expertService;
	@Autowired
	private InspectionItemService itemService;
	@Autowired
	private StandardInspectService standService;
	@Autowired
	private InspectionStationService instationService;
	@Autowired
	private SubstationLedgerManager stationLedgerM;
	@Autowired
	private CimManager cimM;
	@Autowired
	private ManagementUnitService unitService;

	@Autowired
	private SuperDAO dao;
	@Autowired
	private MapDataCache cc;
	/**
	 * 控制是否进行下一步或返回
	 */
	private boolean nextOrBack;
	/**
	 * 当前处于哪一步
	 */
	private String currentStep;
	/**
	 * 传递的参数：计划开始时间
	 */
	private Date startTime;
	/**
	 * 传递的参数：计划结束时间
	 */
	private Date endTime;
	/**
	 * 传递的参数：变电站id数组
	 */
	private String[] selectedStations;
	/**
	 * 传递的参数：评价计划id
	 */
	private String planId;

	/**
	 * 变电站树根节点
	 */
	private TreeNode stationRoot;
	/**
	 * 所有的变电站map缓存
	 */
	private Map<String, Substation> stationMap = new HashMap<String, Substation>();
	/**
	 * 所有的检修范围,<id,ManagementUnitDict>
	 */
	private Map<String,ManagementUnitDict> maintenanceScopesMap = new HashMap<String, ManagementUnitDict>();
	/**
	 * 所有的运维单位
	 */
	private List<ManagementUnitDict> allMaintenance;
	/**
	 * 电压等级
	 */
	private String selectedVol = "0";
	/**
	 * 选中的变电站节点
	 */
	private TreeNode[] selectedSubStationNodes;

	/**
	 * 评价标准树根节点
	 */
	private TreeNode standardRoot;	
	/**
	 * 评价标准树选中的节点
	 */
	private TreeNode[] selectedStandardNodes;	
	/**
	 * 选中的专家节点
	 */
	private TreeNode[] selectedExpertNodes;
	/**
	 * 选取的评价站树根节点
	 */
	private TreeNode selectedStationsRoot;
	/**
	 * 选中需要分配专家的变电站
	 */
	private TreeNode[] selectedAllotStationNodes;
	/**
	 * 专家树根节点
	 */
	private TreeNode expertRoot;

	/**
	 * key:顶级运维部门id
	 * value:专家集合
	 */
	private Map<String,List<InspectionExpert>> deptIdToExperts = new HashMap<String, List<InspectionExpert>>();

	//默认 1位专家/站
	private int expertNum = 1;
	/**
	 * 一键分配，默认选中
	 */
	private boolean auto = true;
	/**
	 * 手动分配
	 */
	private boolean manual = false;
	/**
	 * 保存变电站id选中的专家
	 */
	Map<String, List<InspectionExpert>> stationIdToExperts = new HashMap<String, List<InspectionExpert>>();
	/**
	 * key:选取的变电站对应的检修范围id
	 */
	Map<String,List<Substation>> scopeIdToStations = new HashMap<String, List<Substation>>();

	/**
	 * 部门id对应选中的变电站
	 */
	private Map<String,List<Substation>> deptIdToSelectedSubstations = new HashMap<String, List<Substation>>();
	/**
	 * 部门id对应选中的专家
	 */
	private Map<String,List<InspectionExpert>> deptIdToSelectedExperts = new HashMap<String, List<InspectionExpert>>();
	/**
	 * 标准树节点对应的子节点
	 */
	private Map<String,List<TreeNode>> standIdToChildrenNode = new HashMap<String, List<TreeNode>>();
	/**
	 * 选中的标准树节点
	 */
	private Map<String,TreeNode> standIdToSelectedStandardNode = new HashMap<String, TreeNode>();
	/**
	 * 变电站类型
	 */
	private String stationType;
	/**
	 * 返回的数据
	 */
	private String inspectSelfItemData = "";
	
	private Map<String,ManagementUnitDict> stationIdToManagementUnitDictMap = new HashMap<String, ManagementUnitDict>();

	@PostConstruct
	public void init() {
		initBaseData();
		preInitStationTree();
		initStandardTree();
	}
	
	private void initBaseData() {
		currentStep = "stationSelector";
		stationType = "SMART";
	}

	/**
	 * 初始化变电站树的准备工作
	 */
	public void preInitStationTree() {
		stationMap = cc.getStationid_map();
		genMaintenanceScopesMap();
		try {
			allMaintenance = unitService.getAllMaintenanceManagements();
			initSubStationTree();
		} catch (ManagementUnitException e) {
			e.printStackTrace();
			addErrorMessage("获取所有的运维单位出错");
		}
	}
	/**
	 * 获取检修范围，封装成Map<id,ManagementUnitDict>
	 */
	private void genMaintenanceScopesMap() {
		try {
			List<ManagementUnitDict> allMaintenanceScopes = unitService.getAllMaintenanceScopes();
			for (ManagementUnitDict unit : allMaintenanceScopes) {
				maintenanceScopesMap.put(unit.getId(), unit);
			}
		} catch (ManagementUnitException e) {
			e.printStackTrace();
			addErrorMessage("获取全部的检修范围出错");
		}
	}

	/**
	 * 初始化变电站树
	 * 结构：一级节点：南方电网
	 * 二级节点：检修范围
	 * 三级节点：运维单位
	 * 四级节点：变电站
	 */
	private void initSubStationTree() {
		stationRoot = new DefaultTreeNode();
		try {
			String rootName = unitService.getManagementUnitRoot();
			if(StringUtils.isEmpty(rootName)) {
				rootName = "南方电网";
			}
			// 组织机构的根节点，即南方电网
			DefaultTreeNode rootNode = new DefaultTreeNode("root", rootName, stationRoot);
			// 获取检修范围
			List<ManagementUnitDict> firstLevelChilds = getUnitsByPidFromList(null);
			for (ManagementUnitDict unit : firstLevelChilds) {
				recursionGenChildNode(unit, rootNode);
			}
			rootNode.setExpanded(true);
		} catch (ManagementUnitException e) {
			e.printStackTrace();
		}
	}
	/**
	 * 根据pid，从allMaintenance中获取pid符合条件的记录
	 * pid=null,从所有的运维单位中，获取一级单位，即如果某记录的父单位类型为检修范围，则该父部门设为运维单位的一级单位
	 * @param pid
	 * @return 
	 */
	private List<ManagementUnitDict> getUnitsByPidFromList(String pid) {
		List<ManagementUnitDict> result = new ArrayList<ManagementUnitDict>();
		if(null == pid) {
			Set<ManagementUnitDict> units = new HashSet<ManagementUnitDict>();
			for (ManagementUnitDict unit : allMaintenance) {
				if(maintenanceScopesMap.containsKey(unit.getPid())) {
					units.add(maintenanceScopesMap.get(unit.getPid()));
				}
			}
			result.addAll(units);
		} else {
			for (ManagementUnitDict unit : allMaintenance) {
				if(pid.equals(unit.getPid())) {
					result.add(unit);
				}
			}
		}
		sort(result);
		return result;
	}
	/**
	 * 递归查找下一级节点，
	 * @param dept
	 * @param treeNode
	 */
	private void recursionGenChildNode(ManagementUnitDict unit, TreeNode rootNode) {
		DefaultTreeNode treeNode = new DefaultTreeNode("maintenanceUnit", unit, rootNode);
		if(unit.getUnitType() == ManagementUnitEnum.MAINTENANCE_MANAGEMENT) {// 当类型为运维时，查找其下的变电站
			// 获取该部门下的变电站
			if("0".equals(selectedVol)) {
				selectedVol = null;
			}
			List<SubstationLedger> stationLedgers = stationLedgerM.querySubstationByVoltageAndMaintenanceUnit(selectedVol, unit);
			for (SubstationLedger ledger : stationLedgers) {
				Substation station = stationMap.get(ledger.getCimId());
				DefaultTreeNode node = new DefaultTreeNode("station", station, treeNode);
				if(selectedStations==null) {
					continue;
				}
				for (int i=0;i<selectedStations.length;i++) {
					if(station.getId().equals(selectedStations[i])) {
						node.setSelected(true);
					}
				}
			}
		}
		// 获取该部门下的子部门
		List<ManagementUnitDict> childs = getUnitsByPidFromList(unit.getId());
		for (ManagementUnitDict dict : childs) {
			recursionGenChildNode(dict, treeNode);
		}
	}
	/**
	 * 将ManagementUnitDict按ordered从高到低排序
	 * @param List<ManagementUnitDict>
	 */
	private void sort(List<ManagementUnitDict> list) {
		Collections.sort(list,new Comparator<ManagementUnitDict> () {
			@Override
			public int compare(ManagementUnitDict o1, ManagementUnitDict o2) {
				return o2.getOrdered()-o1.getOrdered();
			}
		});
	}
	/**
	 * 选择变电站后，重新构造树
	 */
	public void changeVoltage(){
		initSubStationTree();
		selectedSubStationNodes = null;
	}
	/**
	 * 处理变电站选中事件
	 */
	public void onStationNodeSelect(NodeSelectEvent event) {
		
	}
	/**
	 * 处理变电站取消选中事件
	 */
	public void onStationNodeUnSelect(NodeUnselectEvent event) {
		
	}
	/**
	 * 初始化评价标准树，构造所有子节点
	 */
	private void initStandardTree() {
		standardRoot = new DefaultTreeNode();
		//获取当前版本的根节点
		try {
			List<StandardInspection> rootStands = standService.findAvailableRoot();
			int i = 0;
			for (StandardInspection rootStand : rootStands) {
				DefaultTreeNode rootStandNode = new DefaultTreeNode(rootStand.getItemType().getValue(),rootStand, standardRoot);
				if(i==0) {
					rootStandNode.setSelected(true);
					standIdToSelectedStandardNode.put(rootStand.getId(), rootStandNode);
				}
				i++;
			}
		} catch (Exception e) {
			e.printStackTrace();
			addErrorMessage("获取可用版本数据过程中发生错误");
		}
		
	}
	/**
	 * 评价标准树节点扩展事件处理函数
	 */
	public void onStandardNodeExpand(NodeExpandEvent event) {
		TreeNode expandNode = event.getTreeNode();
		StandardInspection stand = (StandardInspection) expandNode.getData();
		if(!standIdToChildrenNode.containsKey(stand.getId())) {
			List<TreeNode> standNodes = new ArrayList<TreeNode>();
			List<StandardInspection> lt = standService.findByParentId(stand.getId());
			if(lt!=null) {
				for (StandardInspection standardInspection : lt) {
					DefaultTreeNode standNode = new DefaultTreeNode(standardInspection.getItemType().getValue(),standardInspection, expandNode);
					standNode.setSelected(expandNode.isSelected());
					standNodes.add(standNode);
				}
			}
			standIdToChildrenNode.put(stand.getId(), standNodes);
		}
		if(expandNode.isSelected()) {//该节点已被选中
			List<TreeNode> standNodes = standIdToChildrenNode.get(stand.getId());
			for(TreeNode standNode : standNodes) {
				StandardInspection standard = (StandardInspection) standNode.getData();
				if(!standIdToSelectedStandardNode.containsKey(standard.getId())) {
					standIdToSelectedStandardNode.put(standard.getId(), standNode);
				}
			}
			if(standIdToSelectedStandardNode.containsKey(stand.getId())) {
				standIdToSelectedStandardNode.remove(stand.getId());
			}
		}
	}
	/**
	 * 选择树节点
	 */
	public void onStandardNodeSelect(NodeSelectEvent event) {
		TreeNode selectedNode = event.getTreeNode();
		StandardInspection stand = (StandardInspection) selectedNode.getData();
		if(standIdToChildrenNode.containsKey(stand.getId())) {
			for(TreeNode node :standIdToChildrenNode.get(stand.getId())) {
				StandardInspection standard = (StandardInspection) node.getData();
				if(!standIdToSelectedStandardNode.containsKey(standard.getId())) {
					standIdToSelectedStandardNode.put(standard.getId(), node);
				}
				node.setSelected(true);
			}
		}else {
			standIdToSelectedStandardNode.put(stand.getId(), selectedNode);
		}
	}
	/**
	 * 取消选择树节点
	 * @param event
	 */
	public void onStandardNodeUnSelect(NodeUnselectEvent event) {
		TreeNode selectedNode = event.getTreeNode();
		setParentNodeSelected(selectedNode,false);
		selectedNode.setSelected(false);
		StandardInspection stand = (StandardInspection) selectedNode.getData();
		if(standIdToChildrenNode.containsKey(stand.getId())) {
			for(TreeNode node :standIdToChildrenNode.get(stand.getId())) {
				StandardInspection standard = (StandardInspection) node.getData();
				if(standIdToSelectedStandardNode.containsKey(standard.getId())) {
					standIdToSelectedStandardNode.remove(standard.getId());
				}
				node.setSelected(false);
			}
		}else {
			standIdToSelectedStandardNode.remove(stand.getId());
		}
	}
	/**
	 * 设置其父节点是否选中
	 * @param selectedNode
	 * @param selected
	 */
	private void setParentNodeSelected(TreeNode selectedNode, boolean selected) {
		TreeNode parentNode = selectedNode.getParent();
		if(parentNode!=null) {
			parentNode.setSelected(selected);
			setParentNodeSelected(parentNode,selected);
		}
	}
	
	/**
	 * 根据评价标准树选中的树节点生成对应的评价条目
	 * @param instation 
	 */
	private List<InspectionItem> generateInspectionItems(InspectionStation instation) {
		List<InspectionItem> inspectionItems = new ArrayList<InspectionItem>();
		Map<String,InspectionItem> standardIdToItemMap = new HashMap<String,InspectionItem>();
		for(String standId : standIdToSelectedStandardNode.keySet()){
			TreeNode tn = standIdToSelectedStandardNode.get(standId);
			StandardInspection stand = (StandardInspection) tn.getData();
			try {
				InspectionItem item = itemService.convertFromStandardInspection(stand,planId);
				InspectionItem pItem = getFatherInspectionItem(tn,standardIdToItemMap,inspectionItems,instation);
				addChildInspectionItem(item,inspectionItems,standardIdToItemMap,instation);
				item.setParent(pItem);
				item.setStatus(0);
				item.setStation(instation);
				inspectionItems.add(item);
				standardIdToItemMap.put(stand.getId(), item);
			} catch (ParameterException e) {
				e.printStackTrace();
			}
		}
		return inspectionItems;
	}
	/**
	 * 添加子评价条目
	 * @param pItem
	 * @param items
	 * @param itemMap 
	 * @param instation 
	 * @param instation 
	 * @throws ParameterException
	 */
	private void addChildInspectionItem(InspectionItem pItem, List<InspectionItem> items, Map<String, InspectionItem> itemMap, InspectionStation instation) throws ParameterException {
		List<StandardInspection> stands = standService.findByParentId(pItem.getStandardId());
		if(stands!=null&&!stands.isEmpty()) {
			for (StandardInspection stand : stands) {
				InspectionItem item = itemService.convertFromStandardInspection(stand,planId);
				addChildInspectionItem(item,items,itemMap,instation);
				item.setParent(pItem);
				item.setStatus(0);
				item.setStation(instation);
				items.add(item);
				itemMap.put(stand.getId(), item);
			}
		}
	}
	/**
	 * 获得选中评价标准树节点的父节点对应的评价条目
	 * @param cNode
	 * @param itemMap
	 * @param items
	 * @param instation 
	 * @param instation 
	 * @return
	 * @throws ParameterException
	 */
	private InspectionItem getFatherInspectionItem(TreeNode cNode, Map<String, InspectionItem> itemMap, List<InspectionItem> items, InspectionStation instation) throws ParameterException {
		StandardInspection stand = (StandardInspection)cNode.getData();
		if(stand.getItemType()==ItemTypeEnum.ROOTNAME) {
			return null;
		}
		TreeNode pNode = cNode.getParent();
		if(pNode!=null) {
			StandardInspection pstand = (StandardInspection) pNode.getData();
			if(itemMap.containsKey(pstand.getId())) {//已经存在
				return itemMap.get(pstand.getId());
			}else {
				InspectionItem item = itemService.convertFromStandardInspection(pstand,planId);
				InspectionItem pItem = getFatherInspectionItem(pNode,itemMap,items,instation);
				item.setParent(pItem);
				item.setStatus(0);
				item.setStation(instation);
				items.add(item);
				itemMap.put(pstand.getId(), item);
				return item;
			}
		}
		return null;
	}
	/**
	 * 初始化选取的变电站树
	 * 构造：一级节点：南方电网
	 * 二级节点：检修范围
	 * 三级节点：运维单位
	 * 四级节点：选中的变电站
	 */
	private void initSelectedStationRoot() {
		scopeIdToStations.clear();
		deptIdToSelectedSubstations.clear();
		stationIdToManagementUnitDictMap.clear();
		selectedStationsRoot = new DefaultTreeNode();
		Map<String, TreeNode> scopeNodeMap = new HashMap<String, TreeNode>();
		String rootName = "";
		try {
			rootName = unitService.getManagementUnitRoot();
		} catch (ManagementUnitException e) {
			e.printStackTrace();
		}
		// 组织机构的根节点，即南方电网
		DefaultTreeNode rootNode = new DefaultTreeNode("deptRoot", rootName, selectedStationsRoot);
		if(selectedSubStationNodes!=null&&selectedSubStationNodes.length>0) {
			for(int i=0;i<selectedSubStationNodes.length;i++) {
				TreeNode substationNode = selectedSubStationNodes[i];
				if(substationNode.getType().equals("station")) {
					Substation station = (Substation) substationNode.getData();
					if(station!=null) {
						ManagementUnitDict management = (ManagementUnitDict) substationNode.getParent().getData();
						ManagementUnitDict scope = (ManagementUnitDict) substationNode.getParent().getParent().getData();
						if(!scopeNodeMap.containsKey(scope.getId())) {//该单位第一次出现
							TreeNode deptNode = new DefaultTreeNode("dept",scope,rootNode);
							if(auto) {
								deptNode.setSelectable(false);
							}
							scopeNodeMap.put(scope.getId(), deptNode);
							List<Substation> stationList = new ArrayList<Substation>();
							scopeIdToStations.put(scope.getId(), stationList);
						}
						DefaultTreeNode stationNode = new DefaultTreeNode("station",station, scopeNodeMap.get(scope.getId()));
						if(auto) {
							stationNode.setSelectable(false);
						}
						scopeIdToStations.get(scope.getId()).add(station);
						stationIdToManagementUnitDictMap.put(station.getId(), management);
					}
				}
			}
		}
		rootNode.setExpanded(true);
		if(auto) {
			rootNode.setSelectable(false);
		}
		
	}
	/**
	 * 处理变电站选中事件
	 * @param event
	 */
	public void onAllotStationNodeSelect(NodeSelectEvent event) {
		TreeNode selectedStationNode = event.getTreeNode();
		if("deptRoot".equals(selectedStationNode.getType())) {
			deptIdToSelectedSubstations.clear();
			deptIdToSelectedSubstations.putAll(scopeIdToStations);
			for(TreeNode deptNode : selectedStationNode.getChildren()) {
				deptNode.setSelected(true);
				for(TreeNode node : deptNode.getChildren()) {
					node.setSelected(true);
				}
			}
		}else if("dept".equals(selectedStationNode.getType())) {
			ManagementUnitDict dept = (ManagementUnitDict) selectedStationNode.getData();
			if(deptIdToSelectedSubstations.containsKey(dept.getId())) {
				deptIdToSelectedSubstations.remove(dept.getId());
			}
			deptIdToSelectedSubstations.put(dept.getId(), scopeIdToStations.get(dept.getId()));
			for(TreeNode node : selectedStationNode.getChildren()) {
				node.setSelected(true);
			}
		}else {
			Substation station = (Substation) selectedStationNode.getData();
			TreeNode deptNode = selectedStationNode.getParent();
			ManagementUnitDict dept = (ManagementUnitDict) deptNode.getData();
			if(!deptIdToSelectedSubstations.containsKey(dept.getId())) {
				deptIdToSelectedSubstations.put(dept.getId(), new ArrayList<Substation>());
			}
			deptIdToSelectedSubstations.get(dept.getId()).add(station);
		}
		
	}
	/**
	 * 处理变电站取消选择事件
	 * @param event
	 */
	public void onAllotStationNodeUnSelect(NodeUnselectEvent event) {
		TreeNode selectedStationNode = event.getTreeNode();
		if("deptRoot".equals(selectedStationNode.getType())) {
			deptIdToSelectedSubstations.clear();
			for(TreeNode deptNode : selectedStationNode.getChildren()) {
				deptNode.setSelected(false);
				for(TreeNode node : deptNode.getChildren()) {
					node.setSelected(false);
				}
			}
		}else if("dept".equals(selectedStationNode.getType())) {
			ManagementUnitDict dept = (ManagementUnitDict) selectedStationNode.getData();
			deptIdToSelectedSubstations.remove(dept.getId());
			for(TreeNode node : selectedStationNode.getChildren()) {
				node.setSelected(false);
			}
		}else {
			Substation station = (Substation) selectedStationNode.getData();
			TreeNode deptNode = selectedStationNode.getParent();
			ManagementUnitDict dept = (ManagementUnitDict) deptNode.getData();
			deptIdToSelectedSubstations.get(dept.getId()).remove(station);
		}
	}
	/**
	 * 初始化专家树根节点
	 */
	public void initExpertRoot() {
		deptIdToSelectedExperts.clear();
		expertRoot = new DefaultTreeNode("Root", null);
		List<DepartmentEntityBean> rootDepts = dm.findRootDepts();
		if (rootDepts.size() == 0) {
			return ;
		}
		// 组织机构的根节点，即南方电网
		DepartmentEntityBean rootDept = rootDepts.get(0);
		DefaultTreeNode root = new DefaultTreeNode("deptRoot", rootDept, expertRoot);
		List<DepartmentEntityBean> departments = dm.getDepartmentsByParent(rootDept.getId());
		for (DepartmentEntityBean departmentEntityBean : departments) {
			DefaultTreeNode pdeptNode = new DefaultTreeNode("dept",departmentEntityBean,root);
//			deptIdToExpertTreeDeptNode.put(departmentEntityBean.getId(), pdeptNode);
			addExpertNode(departmentEntityBean.getId(),departmentEntityBean,pdeptNode);
			if(auto) {
				pdeptNode.setSelectable(false);
			}
		}
		root.setExpanded(true);
		if(auto) {
			root.setSelectable(false);
		}
	}

	/**
	 * 添加专家节点
	 * @param id
	 * @param pdept
	 * @param pdeptNode
	 */
	private void addExpertNode(String id, DepartmentEntityBean pdept, DefaultTreeNode pdeptNode) {
		if(!deptIdToExperts.containsKey(id)) {
			deptIdToExperts.put(id, new ArrayList<InspectionExpert>());
		}
		List<InspectionExpert> experts = expertService.findByDeptName(pdept.getName());
		if(experts!=null&&!experts.isEmpty()) {
			for (InspectionExpert inspectionExpert : experts) {
				DefaultTreeNode expertNode = new DefaultTreeNode("expert",inspectionExpert,pdeptNode);
				if(auto) {
					expertNode.setSelectable(false);
				}
			}
			deptIdToExperts.get(id).addAll(experts);
		}
		//该部门下的所有子部门
		List<DepartmentEntityBean> children = dm.getDepartmentsByParent(pdept.getId());
		if(children!=null&&!children.isEmpty()) {
			for (DepartmentEntityBean dept : children) {
				addExpertNode(id,dept,pdeptNode);
			}
		}
		
	}
	/**
	 * 处理专家树节点选中事件
	 * @param event
	 */
	public void onExpertNodeSelect(NodeSelectEvent event) {
		TreeNode selectedExpertNode = event.getTreeNode();
		if("deptRoot".equals(selectedExpertNode.getType())) {//一级节点（南方电网）
			deptIdToSelectedExperts.clear();
			deptIdToSelectedExperts.putAll(deptIdToExperts);
			for(TreeNode deptNode : selectedExpertNode.getChildren()) {
				deptNode.setSelected(true);
				for(TreeNode node : deptNode.getChildren()) {
					node.setSelected(true);
				}
			}
		}else if("dept".equals(selectedExpertNode.getType())) {
			DepartmentEntityBean dept = (DepartmentEntityBean) selectedExpertNode.getData();
			if(deptIdToSelectedExperts.containsKey(dept.getId())) {
				deptIdToSelectedExperts.remove(dept.getId());
			}
			deptIdToSelectedExperts.put(dept.getId(), deptIdToExperts.get(dept.getId()));
			for(TreeNode node : selectedExpertNode.getChildren()) {
				node.setSelected(true);
			}
		}else {
			InspectionExpert expert = (InspectionExpert) selectedExpertNode.getData();
			TreeNode deptNode = selectedExpertNode.getParent();
			DepartmentEntityBean dept = (DepartmentEntityBean) deptNode.getData();
			if(!deptIdToSelectedExperts.containsKey(dept.getId())) {
				deptIdToSelectedExperts.put(dept.getId(), new ArrayList<InspectionExpert>());
			}
			deptIdToSelectedExperts.get(dept.getId()).add(expert);
		}
	}
	/**
	 * 处理专家树节点取消选择事件
	 * @param event
	 */
	public void onExpertNodeUnSelect(NodeUnselectEvent event) {
		TreeNode selectedExpertNode = event.getTreeNode();
		if("deptRoot".equals(selectedExpertNode.getType())) {//一级节点（南方电网）
			deptIdToSelectedExperts.clear();
			for(TreeNode deptNode : selectedExpertNode.getChildren()) {
				deptNode.setSelected(false);
				for(TreeNode node : deptNode.getChildren()) {
					node.setSelected(false);
				}
			}
		}else if("dept".equals(selectedExpertNode.getType())) {
			DepartmentEntityBean dept = (DepartmentEntityBean) selectedExpertNode.getData();
			if(deptIdToSelectedExperts.containsKey(dept.getId())) {
				deptIdToSelectedExperts.remove(dept.getId());
			}
			for(TreeNode node : selectedExpertNode.getChildren()) {
				node.setSelected(false);
			}
		}else {
			InspectionExpert expert = (InspectionExpert) selectedExpertNode.getData();
			TreeNode deptNode = selectedExpertNode.getParent();
			DepartmentEntityBean dept = (DepartmentEntityBean) deptNode.getData();
			deptIdToSelectedExperts.get(dept.getId()).remove(expert);
		}
	}
	
	/**
	 * 处理一键分配选择框change事件函数
	 */
	public void handleAuto() {
		if(auto) {
			manual = false;
			setStationTreeNodeSelectable(false);
			setExpertTreeNodeSelectable(false);
			
		}else {
			manual = true;
			setStationTreeNodeSelectable(true);
			setExpertTreeNodeSelectable(true);
		}
	}
	/**
	 * 处理手动分配选择框change事件函数
	 */
	public void handleManual() {
		if(manual) {
			auto = false;
			setStationTreeNodeSelectable(true);
			setExpertTreeNodeSelectable(true);
		}else {
			auto = true;
			setStationTreeNodeSelectable(false);
			setExpertTreeNodeSelectable(false);
		}
	}
	/**
	 * 设置专家树节点是否可选
	 * @param selectable
	 */
	private void setExpertTreeNodeSelectable(boolean selectable) {
		if(expertRoot!=null) {
			for(TreeNode root : expertRoot.getChildren()) {
				root.setSelectable(selectable);
				for(TreeNode deptNode : root.getChildren()) {
					deptNode.setSelectable(selectable);
					for(TreeNode expertNode : deptNode.getChildren()) {
						expertNode.setSelectable(selectable);
					}
				}
			}
		}
	}
	/**
	 * 获得所有的变电站类型
	 * @return
	 */
	public SubStationTypeEnum[] getStationTypes() {
		return SubStationTypeEnum.values();
	}
	/**
	 * 设置选择变电站树节点是否可选
	 * @param selectable
	 */
	private void setStationTreeNodeSelectable(boolean selectable) {
		if(selectedStationsRoot!=null) {
			for(TreeNode root : selectedStationsRoot.getChildren()) {
				root.setSelectable(selectable);
				for(TreeNode deptNode : root.getChildren()) {
					deptNode.setSelectable(selectable);
					for(TreeNode node : deptNode.getChildren()) {
						node.setSelectable(selectable);
					}
				}
			}
		}
	}	
	/**
	 * 
	 * @param stationId
	 */
	public String getExpertListStr(String stationId) {
		StringBuffer result = new StringBuffer("");
		if(stationIdToExperts.containsKey(stationId)) {
			List<InspectionExpert> expertList = stationIdToExperts.get(stationId);
			if(!expertList.isEmpty()) {
				result.append("（");
				for (InspectionExpert inspectionExpert : expertList) {
					result.append(inspectionExpert.getName()).append(",");
				}
				result.deleteCharAt(result.length()-1);
				result.append("）");
			}
			
		}
		return result.toString();
	}
	/**
	 * 分配
	 */
	public void allot() {
		if(auto) {//一键分配
			Map<String,List<InspectionExpert>> result = new HashMap<String, List<InspectionExpert>>();
			for(String deptId : scopeIdToStations.keySet()) {
				allotOfOrder(scopeIdToStations.get(deptId),deptIdToExperts.get(deptId),expertNum,result);
			}
			for(String stationId : result.keySet()) {
				if(stationIdToExperts.containsKey(stationId)) {
					stationIdToExperts.remove(stationId);
				}
				stationIdToExperts.put(stationId, result.get(stationId));
			}
			addSuccessMessage("专家分配成功！");
		}else {//手动分配
			allotOfManual();				
		}
	}
	/**
	 * 手动分配
	 * 
	 */
	private void allotOfManual() {
		List<Substation> targetStations = new ArrayList<Substation>();
		List<InspectionExpert> targetExperts = new ArrayList<InspectionExpert>();
		if(!deptIdToSelectedSubstations.isEmpty()) {
			for(String deptId : deptIdToSelectedSubstations.keySet()) {
				targetStations.addAll(deptIdToSelectedSubstations.get(deptId));
			}
		}
		if(targetStations.isEmpty()) {
			FacesMessage facesMsg = new FacesMessage(FacesMessage.SEVERITY_WARN,"提示","请选择厂站！");
	    	PrimeFaces.current().dialog().showMessageDynamic(facesMsg);
			return;
		}
		if(!deptIdToSelectedExperts.isEmpty()) {
			for(String deptId : deptIdToSelectedExperts.keySet()) {
				targetExperts.addAll(deptIdToSelectedExperts.get(deptId));
			}
		}
		if(targetExperts.isEmpty()) {
			FacesMessage facesMsg = new FacesMessage(FacesMessage.SEVERITY_WARN,"提示","请为选择的厂站选取专家！");
	    	PrimeFaces.current().dialog().showMessageDynamic(facesMsg);
			return;
		}
		Map<String,List<InspectionExpert>> result = new HashMap<String, List<InspectionExpert>>();
		allotOfOrder(targetStations,targetExperts,expertNum,result);
		for (String stationId : result.keySet()) {
			if(stationIdToExperts.containsKey(stationId)) {
				stationIdToExperts.remove(stationId);
			}
			stationIdToExperts.put(stationId, result.get(stationId));
		}
		addSuccessMessage("专家分配成功！");
	}
	/**
	 * 顺序分配
	 * @param stations
	 * @param experts
	 * @param num
	 * @param result
	 */
	private void allotOfOrder(List<Substation> stations,List<InspectionExpert> experts,int num,Map<String, List<InspectionExpert>> result) {
		if(stations!=null&&!stations.isEmpty()&&experts!=null&&!experts.isEmpty()) {
			int stationCount = stations.size();
			int expertCount = experts.size();
			//遍历选中的厂站，为其分配专家
			for(int i=0;i<stationCount;i++) {
				Substation currentStation = stations.get(i);
				List<InspectionExpert> expertList = new ArrayList<InspectionExpert>();
				if(expertCount>num) {//选择的专家人数大于指定人数
					int base = i*num;
					for(int j=0;j<num;j++) {
						int index = (base+j)%expertCount;
						expertList.add(experts.get(index));
					}
				}else {//选择的专家人数小于或等于指定人数
					expertList.addAll(experts);
				}
				result.put(currentStation.getId(), expertList);
			}
		}
	}
	
	/**
	 * 事件流处理函数
	 * @param event
	 * @return
	 */
	public String onFlowProcess(FlowEvent event) {
		if("stationSelector".equals(currentStep)) {//当前是变电站选择器
			if(selectedSubStationNodes==null||selectedSubStationNodes.length<1) {
				alertErrorMessage("未选择变电站");
				nextOrBack = false;
//			}else if(standIdToSelectedStandardNode.isEmpty()) {
//				alertErrorMessage("未选择评价标准");
			}else {
				nextOrBack = true;
				initSelectedStationRoot();
				initExpertRoot();
			}
		}
		if("expertSelector".equals(currentStep)&&"stationSelector".equals(event.getNewStep())) {//当前处于专家选择器并且要返回到变电站和评价标准选择器
			nextOrBack = true;
		}
		if(nextOrBack) {
			nextOrBack = false;
			currentStep = event.getNewStep();
			return event.getNewStep();
		}else {
			return event.getOldStep();
		}
    }
	/**
	 * 打开帮助弹窗
	 */
	public void openHelpDialog() {
		Map<String, Object> options = new HashMap<String, Object>();
		options.put("resizable", true);
		options.put("draggable", true);
		options.put("modal", false);
		options.put("width", 1000);
		options.put("height", 720);
		Map<String, List<String>> params = new HashMap<>();

		PrimeFaces.current().dialog().openDynamic("/ui/equipmentAssessment/assessmentplan/dialog/allotExperts_help.xhtml",  options,params);
	}
	/**
	 * 保存数据并关闭弹窗
	 * 需要传递的数据：分子公司(acceptScope）---供电局（acceptUnit）---变电站（id、name、voltagelevel）---专家(code name phone）
	 */
	public void saveAndClose() {
		if(saveIsAvailable()) {
			JSONObject r = new JSONObject();
			r.put("stationType", stationType);
			List<InspectionStation> instations = new ArrayList<InspectionStation>();
			for(String scopeId : scopeIdToStations.keySet()) {
				ManagementUnitDict scope = maintenanceScopesMap.get(scopeId);
				for(Substation station : scopeIdToStations.get(scopeId)) {
					InspectionStation instation = new InspectionStation();
					instation.setAcceptScope(scope.getName());
					instation.setAcceptUnit(stationIdToManagementUnitDictMap.get(station.getId()).getName());
					instation.setStationId(station.getId());
					instation.setStationName(station.getName());
					instation.setVoltagelevel(station.getStandVoltagelevel());
					List<InspectionExpert> experts = stationIdToExperts.get(station.getId());
					if(!experts.isEmpty()) {
						InspectionExpert expert = experts.get(0);
						instation.setInspectionExpertId(expert.getCode());
						instation.setInspectionExpert(expert.getName());
						instation.setInspectionExpertPhone(expert.getTelephone());
						instation.setInspectionUnit(expert.getDeptName());
					}
					instations.add(instation);
				}
			}
			r.put("selectedInspectionStations", instations);
			inspectSelfItemData = r.toJSONString();
//			log.info("inspectSelfItemData="+inspectSelfItemData);
			PrimeFaces.current().executeScript("closeAndSave("+inspectSelfItemData+")");
		}
	}
	private boolean saveIsAvailable() {
		int num = 0;
		for(String scopeId : scopeIdToStations.keySet()) {
			List<Substation> stationList = scopeIdToStations.get(scopeId);
			for (Substation substation : stationList) {
				if(stationIdToExperts.containsKey(substation.getId())) {
					List<InspectionExpert> expertList = stationIdToExperts.get(substation.getId());
					if(expertList==null||expertList.isEmpty()) {
						num++;
					}
				}else {
					num++;
				}
			}
		}
		if(num>0) {
			FacesMessage facesMsg = new FacesMessage(FacesMessage.SEVERITY_WARN,"提示"," 您还有 "+num+"个评价厂站未分配专家！");
	    	PrimeFaces.current().dialog().showMessageDynamic(facesMsg);
			return false;
		}else {
			return true;
		}
	}
	
//	public void saveAndClose() {
//		long start = System.currentTimeMillis();
//		int num = 0;
//		for(String deptId : deptIdToStations.keySet()) {
//			List<Substation> stationList = deptIdToStations.get(deptId);
//			for (Substation substation : stationList) {
//				if(stationIdToExperts.containsKey(substation.getId())) {
//					List<InspectionExpert> expertList = stationIdToExperts.get(substation.getId());
//					if(expertList==null||expertList.isEmpty()) {
//						num++;
//					}
//				}else {
//					num++;
//				}
//			}
//		}
//		if(num>0) {
//			FacesMessage facesMsg = new FacesMessage(FacesMessage.SEVERITY_WARN,"提示"," 您还有 "+num+"个评价厂站未分配专家！");
//	    	PrimeFaces.current().dialog().showMessageDynamic(facesMsg);
//			return;
//		}
//		//生成评价条目
//		
//		Set<InspectionStation> inspectionStations = new HashSet<InspectionStation>();
//		for(String deptId : deptIdToStations.keySet()) {
//			ManagementUnitDict acceptScope = null;
//			try {
//				acceptScope = unitService.getManagementUnit(deptId);
//			} catch (ManagementUnitException e) {
//				e.printStackTrace();
//			}
//			List<Substation> stationList = deptIdToStations.get(deptId);
//			for (Substation station : stationList) {
//				InspectionStation instation = new InspectionStation();
//				//1.设置评价站基本信息
//				instation.setId(ObjectId.get().toString());
//				instation.setName(station.getName());//评价厂站名称默认设置为变电站名称
//				instation.setStartTime(startTime);
//				instation.setEndTime(endTime);
//				instation.setStationId(station.getId());
//				instation.setStationName(station.getName());
//				instation.setStatus(0);//未开始
//				instation.setAcceptScope(acceptScope.getName());
//				//2.设置评价标准
//				List<InspectionItem> items = generateInspectionItems(instation);
//				instation.setInspectionItems(items);
//				//3.设置有关专家的信息
//				Set<InspectionExpert> experts = new HashSet<InspectionExpert>();
//				if(stationIdToExperts.containsKey(station.getId())) {
//					experts = new HashSet<InspectionExpert>(stationIdToExperts.get(station.getId()));
//					for (InspectionExpert expert : experts) {
//						instation.setInspectionExpert(expert.getName());
//						instation.setInspectionExpertId(expert.getId());
//						instation.setInspectionExpertPhone(expert.getTelephone());
//					}
//				}
//				inspectionStations.add(instation);
//			}
//		}
//		long end = System.currentTimeMillis();
//		log.info("保存耗时："+(end-start));
//		//关闭弹窗,并返回评价变电站信息
//		PrimeFaces.current().dialog().closeDynamic(inspectionStations);
//	}
	

	public boolean isNextOrBack() {
		return nextOrBack;
	}
	public void setNextOrBack(boolean nextOrBack) {
		this.nextOrBack = nextOrBack;
	}
	
	public TreeNode[] getSelectedStandardNodes() {
		return selectedStandardNodes;
	}
	public void setSelectedStandardNodes(TreeNode[] selectedStandardNodes) {
		this.selectedStandardNodes = selectedStandardNodes;
	}

	public String getCurrentStep() {
		return currentStep;
	}

	public void setCurrentStep(String currentStep) {
		this.currentStep = currentStep;
	}

	public TreeNode[] getSelectedExpertNodes() {
		return selectedExpertNodes;
	}

	public void setSelectedExpertNodes(TreeNode[] selectedExpertNodes) {
		this.selectedExpertNodes = selectedExpertNodes;
	}

	public Date getStartTime() {
		return startTime;
	}

	public void setStartTime(Date startTime) {
		this.startTime = startTime;
	}

	public Date getEndTime() {
		return endTime;
	}

	public void setEndTime(Date endTime) {
		this.endTime = endTime;
	}
	public String[] getSelectedStations() {
		return selectedStations;
	}
	public void setSelectedStations(String[] selectedStations) {
		this.selectedStations = selectedStations;
	}
	public TreeNode getStationRoot() {
		return stationRoot;
	}
	public void setStationRoot(TreeNode stationRoot) {
		this.stationRoot = stationRoot;
	}
	public String getSelectedVol() {
		return selectedVol;
	}
	public void setSelectedVol(String selectedVol) {
		this.selectedVol = selectedVol;
	}
	
	public TreeNode[] getSelectedSubStationNodes() {
		return selectedSubStationNodes;
	}
	public void setSelectedSubStationNodes(TreeNode[] selectedSubStationNodes) {
		this.selectedSubStationNodes = selectedSubStationNodes;
	}
	public void setStationMap(Map<String, Substation> stationMap) {
		this.stationMap = stationMap;
	}
	public TreeNode getStandardRoot() {
		return standardRoot;
	}
	public void setStandardRoot(TreeNode standardRoot) {
		this.standardRoot = standardRoot;
	}
	public TreeNode getSelectedStationsRoot() {
		return selectedStationsRoot;
	}
	public void setSelectedStationsRoot(TreeNode selectedStationsRoot) {
		this.selectedStationsRoot = selectedStationsRoot;
	}
	public TreeNode[] getSelectedAllotStationNodes() {
		return selectedAllotStationNodes;
	}
	public void setSelectedAllotStationNodes(TreeNode[] selectedAllotStationNodes) {
		this.selectedAllotStationNodes = selectedAllotStationNodes;
	}
	public TreeNode getExpertRoot() {
		return expertRoot;
	}
	public void setExpertRoot(TreeNode expertRoot) {
		this.expertRoot = expertRoot;
	}
	public int getExpertNum() {
		return expertNum;
	}
	public void setExpertNum(int expertNum) {
		this.expertNum = expertNum;
	}
	public boolean isAuto() {
		return auto;
	}
	public void setAuto(boolean auto) {
		this.auto = auto;
	}
	public boolean isManual() {
		return manual;
	}
	public void setManual(boolean manual) {
		this.manual = manual;
	}

	public String getStationType() {
		return stationType;
	}

	public void setStationType(String stationType) {
		this.stationType = stationType;
	}
	
}


